#include "window.h"

#include <stdlib.h>

#if WIN32 || WIN64
#include "windows/window_impl.h"
#endif

#include "../gvl/system/system.hpp"

#define PIMPL (*self->internal_)

flip_window* flip_create_window()
{
	flip_window* w = malloc(sizeof(flip_window));
	
	flip_init_keys_native_to_flip();
	
	w->internal_ = flip_create_window_internal();
	w->internal_->common.parent = w;
	
	w->handlers.event = NULL;
	w->handlers.button = NULL;
	
	return w;
}

void flip_destroy_window(flip_window* self)
{
	flip_destroy_window_internal(self->internal_);
	free(self);
}

uint flip_window_width(flip_window* self)
{ return self->internal_->common.width; }

uint flip_window_height(flip_window* self)
{ return self->internal_->common.height; }

int
flip_window_draw(flip_window* self)
{
	// TODO: Call callback
	return 0;
}

int
flip_window_set_mode(flip_window* self, uint width, uint height, int fullscreen)
{
	PIMPL.common.width = width;
	PIMPL.common.height = height;
	set_mode(self->internal_, width, height, fullscreen);
	
	return 0;
}

int
flip_window_extension_supported(flip_window* self, char const* name)
{
	char const* extensions = (char const*)(glGetString(GL_EXTENSIONS));
	if (!strstr(extensions, name))
		return 0;
	return 1;
}

static void
flip_window_default_button(flip_window* self, unsigned id, int state)
{
	flip_event ev;
	
	if(NULL == self->handlers.event)
		return;
	ev.type = flip_ev_button;
	ev.data.button.id = id;
	ev.data.button.state = state;
	self->handlers.event(self, &ev);
}

void
flip_window_default_handlers(flip_window* self)
{
	self->handlers.button = flip_window_default_button;
}

void flip_window_throttle_fps(flip_window* self, int fps)
{
	uint32_t nowMs = gvl_get_ticks();
	int frameDelay = (1000 + fps/2) / fps;
	int sleepTime = frameDelay;
	
	sleepTime -= (nowMs - PIMPL.common.prev_frame_ms);
	if(sleepTime > 0)
		gvl_sleep(sleepTime);
	PIMPL.common.prev_frame_ms += frameDelay;
	
	while(PIMPL.common.prev_frame_ms + 2*frameDelay < gvl_get_ticks())
		PIMPL.common.prev_frame_ms += frameDelay;
		
#if 0
	++state().framesShown;
	if(gvl::get_ticks() >= state().lastFpsMeterMs + 1000)
	{
		state().currentFps = state().framesShown;
		state().lastFpsMeterMs = gvl::get_ticks();
		state().framesShown = 0;
		
		//std::cout << "Fps: " << state().currentFps << std::endl;
	}
#endif
}

int
flip_window_button_pressed(flip_window* self, int id)
{
	if(id < 0 || id > flip_numButtons)
		return 0;
	return PIMPL.common.button_state[id];
}